#pragma once

#include <vector>
#include <map>
#include <set>
#include "config.h"
using namespace std;

class Parent{
public:
	/** Constructor
	 * Creates an empty Follows table.
	 */
	Parent();

	/**
	 * Add a Parent relationship of statement number 1 as parent of statement number 2.
	 * @param stmtNum1 statement number one, the parent statement.
	 * @param stmtNum2 statement number two, the child statement.
	 * @return the index of newly added Parent relationship, -1 if unsuccessful.
	 */
	int addParent(int stmtNum1, int stmtNum2);

	/**
	 * Get a list of all matching statement pairs that stmtNum2 is directly nested in stmtNum1
	 * @param stmtNum1 the parent statement number, can be ANYVALUE.
	 * @param stmtNum2 the child statement number, can be ANYVALUE.
	 * @return a vector of pairs that satisfies the criteria, empty if none satisfies.
	 */
	vector<pair<int, int>> getParent(int stmtNum1, int stmtNum2);
	
	/**
	 * Get a list of all matching statement pairs that stmtNum2 is directly or indirectly nested in stmtNum1
	 * @param stmtNum1 the parent (transitive) statement number, can be ANYVALUE.
	 * @param stmtNum2 the child (transitive) statement number, can be ANYVALUE.
	 * @return a vector of pairs that satisfies the criteria, empty if none satisfies.
	 */
	vector<pair<int, int>> getParentStar(int stmtNum1, int stmtNum2);

private:
	vector<pair<int, int>> parentIndex; /**< A Parent table that contains all pairs of following statements */
	map<int, vector<int>> parentChainIndex; /**< A Parent chain table that maps parent to list of direct child statements */

	/**
	 * Recursively build a list of all transitive parent pairs that are reachable from a specific parent/container statement.
	 * @param result the location where pairs will be stored.
	 * @param from the parent/container statement to start from.
	 * @param it the iteractor pointing to the location of 'from' statement within a map index.
	 */
	void buildPairsFrom(set<pair<int, int>> &result, int from, map<int, vector<int>>::iterator it);

	/**
	 * Build a list of all transitive parent pairs that are destinated to a specific parent/container statement.
	 * @param result the location where pairs will be stored.
	 * @param to the destinated statement.
	 * @param it the iteractor pointing to the location of 'to' statement within a map index.
	 */
	void buildPairsTo(set<pair<int, int>> &result, int to, map<int, vector<int>>::iterator it);

	/**
	 * Build a list of all transitive parent pairs using all data in the parentChainIndex.
	 * @param result the location where pairs will be stored.
	 */
	void buildMeshPairs(set<pair<int, int>> &result);
};